package com.jh.paymentchannel.service;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.jh.paymentchannel.business.TopupPayChannelBusiness;
import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.yh.HttpClientNewUtil;
import com.jh.paymentchannel.util.yh.Signature;

import cn.jh.common.tools.Log;
import cn.jh.common.utils.DateUtil;
import net.sf.json.JSONObject;

@Controller
@EnableAutoConfiguration
public class YHPageRequest {

	private static final Logger log = LoggerFactory.getLogger(YHPageRequest.class);

	@Autowired
	private TopupPayChannelBusiness topupPayChannelBusiness;

	@Autowired
	private Util util;

	@Value("${payment.ipAddress}")
	private String ipAddress;

	// 商户编号
	@Value("${yh.org_no}")
	private String orgNo="00000000518981";

	// 秘钥
	@Value("${yh.key}")
	private String Key;

	// 支付申请地址
	@Value("${yh.payApplyUrl}")
	private String payApplyUrl;

	private static final Charset UTF_8 = StandardCharsets.UTF_8;

	//快捷支付申请
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/yhpayapply")
	public @ResponseBody Object yhpayapply(HttpServletRequest request,
			@RequestParam(value = "ordercode") String orderCode,
			@RequestParam(value = "provinceOfBank") String provinceOfBank,
			@RequestParam(value = "cityOfBank") String cityOfBank,
			@RequestParam(value = "bankBranchName") String bankBranchName
			
			) throws Exception {
		log.info("开始进入快捷支付申请接口=====================");
		log.info("Key====================="+Key);
		log.info("传过来的订单号=========orderCode" + orderCode);

		Map<String, String> map = new TreeMap<String, String>();
		RestTemplate restTemplate = new RestTemplate();
		URI uri = util.getServiceUrl("transactionclear", "error url request!");
		String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
		MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("order_code", orderCode);
		String result = restTemplate.postForObject(url, requestEntity, String.class);
		log.info("接口/v1.0/transactionclear/payment/query/ordercode--RESULT================" + result);
		JSONObject jsonObject;
		JSONObject resultObj;
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询订单信息出错");
			map.put("resp_code", "failed");
			map.put("resp_message", "没有该订单信息");
			return map;
		}
		// 银行卡(支付卡)
		String bankCard = resultObj.getString("bankcard");
		String amount = resultObj.getString("amount");
		String rate = resultObj.getString("rate");
		String extraFee = resultObj.getString("extraFee");
		String userId = resultObj.getString("userid");

		restTemplate = new RestTemplate();
		uri = util.getServiceUrl("user", "error url request!");
		url = uri.toString() + "/v1.0/user/bank/default/userid";
		requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("user_id", userId);
		result = restTemplate.postForObject(url, requestEntity, String.class);

		log.info("RESULT================" + result);
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询默认结算卡出错");
			map.put("resp_code", "failed");
			map.put("channel_type", "yh");
			map.put("resp_message", "查询默认结算卡有误");
			return map;
		}
		String respcode = jsonObject.getString("resp_code");
		if (!"000000".equals(respcode)) {

			map.put("resp_code", "failed");
			map.put("channel_type", "yh");
			map.put("resp_message", "没有结算卡");
			return map;
		}
		
		String cardNo = resultObj.getString("cardNo");// 默认提现卡卡号
		String bankName = resultObj.getString("bankName");//提现卡银行名称
		String userName = resultObj.getString("userName");// 用户姓名
		String certId = resultObj.getString("idcard");// 身份证号
		String phone = resultObj.getString("phone");//手机号

		restTemplate = new RestTemplate();
		uri = util.getServiceUrl("user", "error url request!");
		url = uri.toString() + "/v1.0/user/bank/default/cardno";
		requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("cardno", bankCard);
		requestEntity.add("type", "0");
		result = restTemplate.postForObject(url, requestEntity, String.class);
		log.info("接口/v1.0/user/bank/default/cardno--RESULT================" + result);
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询信用卡出错");
			map.put("resp_code", "failed");
			map.put("resp_message", "查询信用卡有误");
			return map;
		}

		String payBankName = resultObj.getString("bankName"); // 支付卡银行名称
		
		log.info("没有转换过的银行名称========payBankName==="+payBankName+"&&&&&&&bankName==="+bankName);
		
		//将银行名称转换为通道支持的银行名称
		String bankName1 = Util.strSub(bankName);
		String payBankName1 = Util.strSub(payBankName);
		
		log.info("已经转换过的银行名称========payBankName1==="+payBankName1+"&&&&&&&bankName1==="+bankName1);
		
		//到账卡银行编码
		String bankCode;
		try {
			bankCode = topupPayChannelBusiness.getBankCodeByBankName(bankName1);
		} catch (Exception e) {
			log.error("查询提现卡银行编码出错啦====="+e);
			map.put("resp_code", "failed");
			map.put("channel_type", "yh");
			map.put("resp_message", "查询提现卡银行编码出错啦");
			return map;
		}
		
		//支付卡银行编码
		String payBankCode;
		try {
			payBankCode = topupPayChannelBusiness.getBankCodeByBankName(payBankName1);
		} catch (Exception e) {
			log.error("查询支付卡银行编码出错啦====="+e);
			map.put("resp_code", "failed");
			map.put("channel_type", "yh");
			map.put("resp_message", "查询支付卡银行编码出错啦");
			return map;
		}

		// 手续费
		BigDecimal bigamount = new BigDecimal(amount);
		BigDecimal bigrate = new BigDecimal(rate);
		BigDecimal bigextraFee = new BigDecimal(extraFee);
		// Bigcecimal类型的运算
		BigDecimal multiply = bigamount.multiply(bigrate);

		// 小数点后2位向上进1位
		BigDecimal setScale = multiply.setScale(2, RoundingMode.CEILING);
		BigDecimal add = setScale.add(bigextraFee);
		
		//总金额减去手续费后的结算金额
		BigDecimal subtract = bigamount.subtract(add);
		
		// 交易金额变成以分为单位
		String Amount = new BigDecimal(amount).multiply(new BigDecimal("100")).setScale(0).toString();

		//结算金额变成以分为单位
		String settlement = new BigDecimal(subtract + "").multiply(new BigDecimal("100")).setScale(0).toString();
		
		log.info("结算金额======settlement========" + settlement);
		
		SortedMap<String, String> dto = new TreeMap<String, String>();
		
		dto.put("versionId", "1.0");// 服务版本号
		dto.put("orderAmount", Amount);// 订单金额(以分为单位)
		dto.put("orderDate", DateUtil.getyyyyMMddHHmmssDateFormat(new Date()));// 订单日期
		dto.put("currency", "RMB");// 货币类型
		dto.put("transType", "0008");// 交易类别
		dto.put("asynNotifyUrl", ipAddress+"/v1.0/paymentchannel/topup/yh/notify_call");// 异步通知URL
		dto.put("synNotifyUrl", ipAddress+"/v1.0/paymentchannel/topup/yh/return_call");// 同步通知URL
		dto.put("signType", "MD5");// 加密方式
		dto.put("merId", "00000000518981");// 商户编号
		dto.put("prdOrdNo", orderCode);// 商户订单号
		dto.put("payMode", "00019");// 支付方式
		dto.put("tranChannel", payBankCode);// 银行编码
		dto.put("receivableType", "D00");// 到账类型
		dto.put("prdName", "充值缴费");// 商品名称
		dto.put("acctNo", bankCard);// 消费卡号
		dto.put("balanceAmt", settlement);// 结算金额
		dto.put("balanceAcctNo", cardNo);// 清算卡号
		dto.put("cerdId", certId);// 开户人身份证
		dto.put("customerName", userName);// 开户人姓名
		dto.put("phoneNo", phone);// 开户人手机号
		dto.put("iscompay", "0");// 0对私 1对公
		dto.put("balanceBankCode", bankCode);// 	清算银行卡编码
		dto.put("rcvProvince", provinceOfBank);// 开户行省
		dto.put("rcvCity", cityOfBank);// 开户行市
		
		log.info("dto======" + dto);
		
		String sign = Signature.createSign(dto, Key);
		
		dto.put("signData", sign);// 加密数据
		
		log.info("sign======" + sign);
		
		String pageContent = HttpClientNewUtil.post(payApplyUrl, dto);
		log.info("我是返回的pageContent======="+pageContent);
		
		map.put("resp_code", "success");
		map.put("channel_type", "yh");
		map.put("pageContent", pageContent);
		//map.put("redirect_url", ipAddress + "/v1.0/paymentchannel/topup/toyhback");
		return map;
		
	}
	
	

	//页面中转接口
	@RequestMapping(method = RequestMethod.GET, value = "/v1.0/paymentchannel/topup/toyhbankinfo")
	public String returnjfapipay(HttpServletRequest request, HttpServletResponse response, Model model)
			throws IOException {
		// 设置编码
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		String bankName = request.getParameter("bankName");//结算卡银行名称
		String bankNo = request.getParameter("bankNo");//结算卡卡号
		String amount = request.getParameter("amount");
		String ordercode = request.getParameter("ordercode");
		String provinceOfBank = request.getParameter("provinceOfBank");
		String cityOfBank = request.getParameter("cityOfBank");
		String bankBranchName = request.getParameter("bankBranchName");
		String bankBranchId = request.getParameter("bankBranchId");
		String cardType = request.getParameter("cardType");
		String isRegister = request.getParameter("isRegister");

		
		model.addAttribute("bankName", bankName);
		model.addAttribute("bankNo",bankNo);
		model.addAttribute("amount", amount);
		model.addAttribute("ordercode", ordercode);
		model.addAttribute("provinceOfBank", provinceOfBank);
		model.addAttribute("cityOfBank", cityOfBank);
		model.addAttribute("bankBranchName", bankBranchName);
		model.addAttribute("bankBranchId", bankBranchId);
		model.addAttribute("cardType", cardType);
		model.addAttribute("isRegister", isRegister);
		
		return "yhbankInfo";
		
	}

	
	//请求支付申请接口返回的页面中转接口
	@RequestMapping(method = RequestMethod.GET, value = "/v1.0/paymentchannel/topup/toyhback")
	public void returnyhback(HttpServletRequest request, HttpServletResponse response, Model model)
			throws IOException {
		// 设置编码
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		String pageContent = request.getParameter("pageContent");//结算卡银行名称
		
		PrintWriter writer = response.getWriter();
		writer.print(pageContent);
		
		writer.close();
		
	}
	
	
	//支付申请接口同步通知
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/yh/return_call")
	public String yhPayReturnCallback(HttpServletRequest request, HttpServletResponse response

	) throws Exception {
		
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		log.info("同步通知进来了");
		Enumeration e = request.getParameterNames();
		SortedMap<String, String> map = new TreeMap<String, String>();
		while (e.hasMoreElements()) {
			String param = (String) e.nextElement();
			map.put(param, request.getParameter(param));
		}
		
		log.info("map============"+map);
		
		String signData = "";
		if(map.get("signData") != null) {
			signData = map.get("signData").toString();
		}
		
		String orderStatus = "";
		if(map.get("orderStatus") != null) {
			orderStatus = map.get("orderStatus").toString();
		}
		
		boolean isSign = false;
		if("MD5".equalsIgnoreCase(map.get("signType").toString())){
			//#.md5编码并转成大写 签名：
			map.remove("signData");
			String sign = Signature.createSign(map,Key);
			
			isSign = signData.equalsIgnoreCase(sign);
        }
		/*String sendMsg = "<root><merchantRes merId=\"" + merId + "\" prdOrdNo=\"" + prdOrdNo + "\" orderAmount=\"" + orderAmount 
				+ "\" orderDate=\"" + orderDate + "\" verifyResult=\"" + verifyResult + "\"/></root>";*/
		/*OutputStream outStr = response.getOutputStream();
		//成功的话返回SUCCESS
		if(isSign)
			outStr.write("SUCCESS".getBytes());
		else
			outStr.write("FAIL".getBytes());

		outStr.flush();
		outStr.close();*/
		
		if ("01".equals(orderStatus)){
			log.info("同步回调成功");
			return "sdjsuccess";
		}else {
			log.info("同步回调失败");
			return "sdjerror";
		}
		
	}
	
	
	// 支付申请接口异步回调
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/yh/notify_call")
	public void yhPayNotifyCallback(HttpServletRequest request, HttpServletResponse response

	) throws Exception {

		log.info("异步回调进来了");
		Enumeration e = request.getParameterNames();
		SortedMap<String, String> map = new TreeMap<String, String>();
		while (e.hasMoreElements()) {
			String param = (String) e.nextElement();
			map.put(param, request.getParameter(param));
		}
		
		log.info("map============"+map);
		
		String signData = "";
		if(map.get("signData") != null) {
			signData = map.get("signData").toString();
		}
		
		String orderStatus = "";
		if(map.get("orderStatus") != null) {
			orderStatus = map.get("orderStatus").toString();
		}
		
		String dfStatus = "";
		if(map.get("dfStatus") != null) {
			dfStatus = map.get("dfStatus").toString();
		} 
		
		String prdOrdNo = "";
		if(map.get("prdOrdNo") != null) {
			prdOrdNo = map.get("prdOrdNo").toString();
		} 
		
		boolean isSign = false;
		if("MD5".equalsIgnoreCase(map.get("signType").toString())){
			//#.md5编码并转成大写 签名：
			map.remove("signData");
			String sign = Signature.createSign(map,Key);
			
			isSign = signData.equalsIgnoreCase(sign);
        }
		/*String sendMsg = "<root><merchantRes merId=\"" + merId + "\" prdOrdNo=\"" + prdOrdNo + "\" orderAmount=\"" + orderAmount 
				+ "\" orderDate=\"" + orderDate + "\" verifyResult=\"" + verifyResult + "\"/></root>";*/
		OutputStream outStr = response.getOutputStream();
		//成功的话返回SUCCESS
		if(isSign)
			outStr.write("SUCCESS".getBytes());
		else
			outStr.write("FAIL".getBytes());

		outStr.flush();
		outStr.close();
		
		try {
			Log.setLogFlag(true);
			log.info("交易： 订单结果异步通知===================");
			if ("01".equals(orderStatus)&&"01".equals(dfStatus)) { // 订单已支付;

				// 1、检查Amount和商户系统的订单金额是否一致
				// 2、订单支付成功的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理）；
				// 3、返回响应内容

				synchronized (this) {
					// **更新订单状态*//*
					// **调用下单，需要得到用户的订单信息*//*
					RestTemplate restTemplate = new RestTemplate();

					URI uri = util.getServiceUrl("transactionclear", "error url request!");
					String url = uri.toString() + "/v1.0/transactionclear/payment/update";

					// **根据的用户手机号码查询用户的基本信息*//*
					MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
					requestEntity.add("status", "1");
					requestEntity.add("order_code", prdOrdNo);
					String result = restTemplate.postForObject(url, requestEntity, String.class);

					log.info("订单状态修改成功===================");

					// **判断是否有外放的通道的处理， 如果有那么继续回调外放哦*//*
					/*uri = util.getServiceUrl("transactionclear", "error url request!");
					url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";

					requestEntity = new LinkedMultiValueMap<String, String>();
					//requestEntity.add("order_code", orderId);
					result = restTemplate.postForObject(url, requestEntity, String.class);

					JSONObject jsonObject = JSONObject.fromObject(result);
					JSONObject resultObj = jsonObject.getJSONObject("result");
					String outMerOrdercode = resultObj.getString("outMerOrdercode");
					String orderdesc = resultObj.getString("desc");
					String phone = resultObj.getString("phone");
					String tranamount = resultObj.getString("amount");
					String channelTag = resultObj.getString("channelTag");
					String notifyURL = resultObj.getString("outNotifyUrl");
					if (outMerOrdercode != null && !outMerOrdercode.equalsIgnoreCase("")) {
						uri = util.getServiceUrl("channel", "error url request!");
						url = uri.toString() + "/v1.0/channel/callback/yilian/notify_call";
						requestEntity = new LinkedMultiValueMap<String, String>();
						requestEntity.add("merchant_no", phone);
						requestEntity.add("amount", tranamount);
						requestEntity.add("channel_tag", channelTag);
						requestEntity.add("order_desc", URLEncoder.encode(orderdesc, "UTF-8"));
						requestEntity.add("order_code", outMerOrdercode);
						requestEntity.add("sys_order", prdOrdNo);
						requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
						result = restTemplate.postForObject(url, requestEntity, String.class);
					}*/

					log.info("订单已支付并代付成功!");
				}
			}else if("01".equals(orderStatus)&&"02".equals(dfStatus)){
				
				log.info("订单代付处理中!");
				
			} else {
				// 1、订单支付失败的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理，避免成功后又修改为失败）；
				// 2、返回响应内容

				log.info("订单支付失败!");
			}
		} catch (Exception exc) {
			log.error(exc.getMessage());
		}
		log.info("-----处理完成----");
	}


}
